import LXCOM from '../common/common.js'
import { CoordTRFUtil } from '../common/tools/coordtool.js'
import utilfuncs from '../common/tools/utilfuncs.js';
var funcs = utilfuncs.UtilFuncs;

import arrowutil from '../graph/paintutil/arrowutil.js';
import { IncludeAngleUtil } from '../graph/paintutil/includeAngleUtil.js';
import absdatamanager from './absdatamanager.js';

import { DisAbsorbPointSvc } from './auxdismng/disaborbpointsvc.js';
import {LGXEnums}  from '../common/sysenum.js';


const absorbDisLenth = 20;
const absorbColorStr = 'rgb(' + 0 + "," + 255 + "," + 0 + ")";

class AbsorbLineSec {
    constructor() {
        this.stPoint = new LXCOM.LGXPoint();
        this.endPoint = new LXCOM.LGXPoint();
        this.display = 0;
        this.destStPoint = new LXCOM.LGXPoint();
        this.destEndPoint = new LXCOM.LGXPoint();
    }
}
class AbsorbRayLine {
    constructor() {
        this.stPoint = new LXCOM.LGXPoint();
        this.endPoint = new LXCOM.LGXPoint();
        this.color = new LXCOM.LGXColor();
        this.color.setVal(128, 0, 0);
        this.lineWidth = 1;
        this.display = 0;
        this.parallelRay1 = null;
        this.parallelRay2 = null;
    }
}

class AbsorbPoint {
    constructor() {
        this.pt = new LXCOM.LGXPoint();
        this.color = new LXCOM.LGXColor();
        this.color.setVal(255, 255, 0);
        this.lineWidth = 1;
        this.display = 1;
        this.kind = LGXEnums.AuxPointKind.commonPt;//0-默认，十字；1--吸附实心圆
    }
    setPt(pt) {
        this.pt.clone(pt);
    }
    setDisplay(v) {
        this.display = v;
    }
    setKind(kind) {
        this.kind = kind;
    }
}


class TSameSizeGraphGroup{
    constructor(kind){
        this.graph = null;
        this.dstGraph = null;
        this.kind = kind;
    }

    setData(graph,dstGraph){
        this.graph = graph;
        this.dstGraph = dstGraph;
    }
}

class AuxDataManager  extends absdatamanager.AbsDataManager{
    constructor(modeName) {
        super(modeName)
        this.m_pXAbsorbRayLine = new AbsorbRayLine();//水平对齐指示线
        this.m_pXAbsorbRayLine.color.setVal(0, 0, 255);
        this.m_pYAbsorbRayLine = new AbsorbRayLine();//垂直对齐指示线
        this.m_pYAbsorbRayLine.color.setVal(0, 255, 0);

        this.m_pAbsorbPoint = new AbsorbPoint();//吸附点标识
        this.m_pVerticalLine = new AbsorbLineSec();//垂直指示线
        this.m_pParallelLine = new AbsorbLineSec();//平行指示线
        this.m_pInterLine = new AbsorbLineSec();//夹角指示线
        this.m_hornSameSizeGroup = new TSameSizeGraphGroup("horn");
        this.m_vertSameSizeGroup = new TSameSizeGraphGroup("vert");
    }

    display(map, mapInfo) {
        let t0 = +new Date(); 
        this.displayXYRayLine(map, mapInfo);
        DisAbsorbPointSvc.display(this.m_pAbsorbPoint,map, mapInfo);
        map.save();
        this.displayVerticalLine(map, mapInfo);
        this.displayParalelLine(map, mapInfo);
        this.displayIncludeAngle(map, mapInfo);
        this.disHornSameGraphGroup(map,mapInfo);
        this.disVertSameGraphGroup(map,mapInfo);
        map.restore();
        let t1 = +new Date(); 
        // console.log("timeelapse:" + (t1-t0));
    }

    resetProcessingEdgeDirLine(stPoint, endPoint, edgeKind, display, parallelRay1, parallelRay2) {
        var rayLine = this.m_pXAbsorbRayLine;
        if (edgeKind == 1) {
            rayLine = this.m_pXAbsorbRayLine;
        }
        else if (edgeKind == 2) {
            rayLine = this.m_pYAbsorbRayLine;
        }
        if (rayLine == null) {
            return;
        }
        rayLine.stPoint.clone(stPoint);
        rayLine.endPoint.clone(endPoint);
        rayLine.display = display;
        rayLine.parallelRay1 = parallelRay1;
        rayLine.parallelRay2 = parallelRay2;
    }

    displayXYRayLine(map, mapInfo) {
        this.displayRayLine(this.m_pXAbsorbRayLine, map, mapInfo);
        this.displayRayLine(this.m_pYAbsorbRayLine, map, mapInfo);
    }

    disHornSameGraphGroup(map,mapInfo){
        if (!this.m_hornSameSizeGroup.graph) {
            return;
        }

        let lbPt1 = this.m_hornSameSizeGroup.graph.getZone().ltPt();
        let rbPt1 = this.m_hornSameSizeGroup.graph.getZone().rtPt();
        let dir1 = {m:0,n:1,p:0};

        let lbPt2 = this.m_hornSameSizeGroup.dstGraph.getZone().lbPt();
        let rbPt2 = this.m_hornSameSizeGroup.dstGraph.getZone().rbPt();
        let dir2 = {m:0,n:-1,p:0};

        map.save();
        map.lineWidth = 1;
        var colorStr = 'rgb(' + 0 + "," + 255 + "," + 0 + ")";
        map.strokeStyle = colorStr;
        this.displayLineSec(lbPt1,rbPt1,dir1, map, mapInfo);
        this.displayDimEdge(lbPt1,rbPt1,dir1, map, mapInfo);

        this.displayLineSec(lbPt2,rbPt2,dir2, map, mapInfo);
        this.displayDimEdge(lbPt2,rbPt2,dir2, map, mapInfo);
        map.restore();
    }

    disVertSameGraphGroup(map,mapInfo){
        if (!this.m_vertSameSizeGroup.graph) {
            return;
        }

        let rbPt1 = this.m_vertSameSizeGroup.graph.getZone().lbPt();
        let rtPt1 = this.m_vertSameSizeGroup.graph.getZone().ltPt();
        let dir1 = {m:-1,n:0,p:0};

        let rbPt2 = this.m_vertSameSizeGroup.dstGraph.getZone().rbPt();
        let rtPt2 = this.m_vertSameSizeGroup.dstGraph.getZone().rtPt();
        let dir2 = {m:1,n:0,p:0};

        map.save();
        map.lineWidth = 1;
        var colorStr = 'rgb(' + 0 + "," + 255 + "," + 0 + ")";
        map.strokeStyle = colorStr;
        this.displayLineSec(rbPt1,rtPt1,dir1, map, mapInfo);
        this.displayDimEdge(rbPt1,rtPt1,dir1, map, mapInfo);

        this.displayLineSec(rbPt2,rtPt2,dir2, map, mapInfo);
        this.displayDimEdge(rbPt2,rtPt2,dir2, map, mapInfo);
        map.restore();
    }

    displayDimEdge(p1, p2,dir, map, mapInfo) {
        let rst = this.getDispLineSecTwoEndPt(p1, p2,dir);
        if (!rst){
            return ;
        }
        map.beginPath();
        map.lineWidth = 1;
        
        let disp1 = rst.disp1;
        let disp2 = rst.disp2;
        let vector = funcs.getVector(p1, p2);
        this.displaySingleDimEdge(p1, p2, disp1, vector, map, mapInfo);
        this.displaySingleDimEdge(p1, p2, disp2, vector, map, mapInfo);
        map.stroke();
        map.closePath();
    }

    displaySingleDimEdge(p1, p2, disp1, vector, map, mapInfo) {
        let scaling = mapInfo.getScaling();
        let edgeGap = 10 / scaling;
        let verticalVector = vector.rotateCopy(90);

        let interPoint1 = funcs.getTwoLineInterPos(p1, vector, disp1, verticalVector);
        let disp1ToInterPtVector = funcs.getVector(disp1, interPoint1);
        let len1 = funcs.distancePoint(disp1, interPoint1, 1);
        let nearLen = len1 - edgeGap;
        let x = disp1.x + nearLen * disp1ToInterPtVector.m;
        let y = disp1.y + nearLen * disp1ToInterPtVector.n;
        let nearPt1 = { x, y };

        x = disp1.x - edgeGap * disp1ToInterPtVector.m;
        y = disp1.y - edgeGap * disp1ToInterPtVector.n;
        let farPt1 = { x, y };

        let disNearPt1 = CoordTRFUtil.world2Screen(nearPt1, mapInfo);
        var disFarPt1 = CoordTRFUtil.world2Screen(farPt1, mapInfo);
        map.moveTo(disNearPt1.x, disNearPt1.y);
        map.lineTo(disFarPt1.x, disFarPt1.y);
    }


    displayLineSec(p1, p2,dir, map, mapInfo) {
        let rst = this.getDispLineSecTwoEndPt(p1, p2,dir);
        if (!rst){
            return ;
        }

        map.beginPath();
        map.lineWidth = 1;

        let disp1 = rst.disp1;
        let disp2 = rst.disp2;

        var sp1 = CoordTRFUtil.world2Screen(disp1, mapInfo);
        var sp2 = CoordTRFUtil.world2Screen(disp2, mapInfo);

        map.moveTo(sp1.x, sp1.y);
        map.lineTo(sp2.x, sp2.y);

        map.stroke();
        map.closePath();

        this.displayArrow(disp1, disp2, map, mapInfo);
        this.displayArrow(disp2, disp1, map, mapInfo);
    }

    displayArrow(p1, p2, map, mapInfo) {
        let vector = funcs.getVector(p1, p2);
        arrowutil.ArrowUtil.dis(p1, vector, map, mapInfo,"#00ff00","triangle_mid_fill_close");
    }

    getDispLineSecTwoEndPt(p1, p2,dir) {
        const offgap = 20;
        let mousePt = { x: (p1.x + p2.x)/2, y: (p1.y + p2.y)/2 };
        mousePt.x = mousePt.x + dir.m*offgap;
        mousePt.y = mousePt.y + dir.n*offgap;

        let vector = funcs.getVector(p1, p2);
        let verticalVector = vector.rotateCopy(90);
        let interPoint = funcs.getTwoLineInterPos(p1, vector, mousePt, verticalVector);
        if (!interPoint){
            console.log(p1,p2);
            return null;
        }

        let midToP1Vector = funcs.getVector(interPoint, p1);
        let dis1 = funcs.distancePoint(p1, interPoint);
        let midToP2Vector = funcs.getVector(interPoint, p2);
        let dis2 = funcs.distancePoint(p2, interPoint);

        let x = mousePt.x + dis1 * midToP1Vector.m;
        let y = mousePt.y + dis1 * midToP1Vector.n;
        let disp1 = { x, y };

        x = mousePt.x + dis2 * midToP2Vector.m;
        y = mousePt.y + dis2 * midToP2Vector.n;
        let disp2 = { x, y };

        let gap = funcs.distancePoint(mousePt, interPoint, 1);
        return { disp1, disp2, gap };
    }

    displayRayLine(rayLine, map, mapInfo) {
        if (rayLine.display != 1) {
            return;
        }
        map.save();
        map.setLineDash([5, 5]);
        map.lineWidth = rayLine.lineWidth;
        var r = rayLine.color.red;
        var g = rayLine.color.green;
        var b = rayLine.color.blue;
        var colorStr = 'rgb(' + r + "," + g + "," + b + ")";
        map.strokeStyle = colorStr;

        map.beginPath();
        var p1 = CoordTRFUtil.world2Screen(rayLine.stPoint, mapInfo);
        map.moveTo(p1.x, p1.y);

        let p2 = CoordTRFUtil.world2Screen(rayLine.endPoint, mapInfo);
        map.lineTo(p2.x, p2.y);

        map.stroke();
        map.closePath();

        this.displayParalelRayLine(rayLine.parallelRay1,p1,p2,map, mapInfo);
        this.displayParalelRayLine(rayLine.parallelRay2,p1,p2,map, mapInfo);

        map.setLineDash([5, 0]);
        map.restore();
        // rayLine.display = 0;
    }

    displayParalelRayLine(parallelRay,p1,p2, map, mapInfo) {
        if (!parallelRay) {
            return;
        }

        let halfWid = parallelRay.offset * mapInfo.getScaling();
        let dir = parallelRay.dir;
        map.beginPath();
        map.moveTo(p1.x + halfWid * dir.m, p1.y + dir.n * halfWid);
        map.lineTo(p2.x + halfWid * dir.m, p2.y + dir.n * halfWid);
        map.stroke();
        map.closePath();
    }

    

    getPointOnLine(p1, p2, lenth) {
        let vct = new LXCOM.LGXVector();
        vct.setBy2Pt(p1, p2);
        let x = p1.x + lenth * vct.m;
        let y = p1.y + lenth * vct.n;
        return { x, y };
    }



    //正在绘制的线路和前面的线段如果垂直，则显示垂直标识
    displayVerticalLine(map, mapInfo) {
        let rayLine = this.m_pVerticalLine;
        if (rayLine.display != 1) {
            return;
        }

        let len = absorbDisLenth / mapInfo.getScaling();
        let p1 = this.getPointOnLine(rayLine.stPoint, rayLine.endPoint, len);
        let p2 = this.getPointOnLine(rayLine.destStPoint, rayLine.destEndPoint, len);

        let vct1 = funcs.getVector(rayLine.stPoint, rayLine.endPoint);
        let vct2 = funcs.getVector(rayLine.destStPoint, rayLine.destEndPoint);

        let interPoint = funcs.getTwoLineInterPos(p1, vct2, p2, vct1);
        if (!interPoint) {
            return;
        }

        map.save();
        map.beginPath();
        map.lineWidth = 1;
        map.strokeStyle = absorbColorStr;

        var sp1 = CoordTRFUtil.world2Screen(p1, mapInfo);
        map.moveTo(sp1.x, sp1.y);

        var spInter = CoordTRFUtil.world2Screen(interPoint, mapInfo);
        map.lineTo(spInter.x, spInter.y);

        var sp2 = CoordTRFUtil.world2Screen(p2, mapInfo);
        map.lineTo(sp2.x, sp2.y);
        map.stroke();
        map.closePath();
        map.restore();
    }

    //在平行线间显示一条临时的垂直线，并标出相平行线间的距离
    displayParalelLine(map, mapInfo) {
        let rayLine = this.m_pParallelLine;
        if (rayLine.display != 1) {
            return;
        }
        console.log("displayParalelLine******");

        let midx = (rayLine.destStPoint.x + rayLine.destEndPoint.x) / 2;
        let midy = (rayLine.destStPoint.y + rayLine.destEndPoint.y) / 2;
        let midpt = { x: midx, y: midy };

        let lineVector = funcs.getVector(rayLine.stPoint, rayLine.endPoint);
        let verticalLineVct = lineVector.cloneCopy();
        verticalLineVct.rotate(90);

        let interPoint = funcs.getTwoLineInterPos(midpt, verticalLineVct, rayLine.stPoint, lineVector);
        if (!interPoint) {
            return;
        }

        map.save();
        map.beginPath();
        map.lineWidth = 1;
        map.strokeStyle = absorbColorStr;

        var sp1 = CoordTRFUtil.world2Screen(midpt, mapInfo);
        map.moveTo(sp1.x, sp1.y);

        var spInter = CoordTRFUtil.world2Screen(interPoint, mapInfo);
        map.lineTo(spInter.x, spInter.y);

        map.stroke();
        map.closePath();

        //如果interPoint不在rayLine.stPoint, rayLine.endPoint组成的线段上，则要做一条从该线段临近端点到
        //interPoint虚线

        let interPtInLineSecFlag = funcs.chkPointOnLineSec(interPoint, rayLine.stPoint, rayLine.endPoint);
        if (!interPtInLineSecFlag) {
            console.log("Math.abs(vct1Rot2vct2Angle) < 1");
            //旋转角小于1（实际数学意义上应该是完全重合，此处考虑精度问题）
            //此时表示交点在线外，从临近点做一条虚线连上来
            let dis1 = funcs.distancePoint(interPoint, rayLine.stPoint, 1);
            let dis2 = funcs.distancePoint(interPoint, rayLine.endPoint, 1);
            let newLineStPt = rayLine.stPoint;
            if (dis2 < dis1) {
                newLineStPt = rayLine.endPoint;
            }
            var sp1 = CoordTRFUtil.world2Screen(newLineStPt, mapInfo);
            map.moveTo(sp1.x, sp1.y);

            var spInter = CoordTRFUtil.world2Screen(interPoint, mapInfo);
            map.lineTo(spInter.x, spInter.y);

            map.stroke();
            map.closePath();
        }


        let vector = funcs.getVector(midpt, interPoint);
        arrowutil.ArrowUtil.dis(midpt, vector, map, mapInfo, absorbColorStr, false, false);
        vector.invert();
        arrowutil.ArrowUtil.dis(interPoint, vector, map, mapInfo, absorbColorStr, false, false);

        {
            map.fillStyle = absorbColorStr;
            var canvasfont = "12px 仿宋";
            map.font = canvasfont;
            let text = funcs.distancePoint(midpt, interPoint, 1);
            text = text.toFixed(2);

            var p1 = CoordTRFUtil.world2Screen(midpt, mapInfo);
            var p2 = CoordTRFUtil.world2Screen(interPoint, mapInfo);

            let tx = (p1.x + p2.x) / 2;
            let ty = (p1.y + p2.y) / 2;
            map.fillText(text, tx, ty);
        }

        map.restore();
    }

    //在平行线间显示一条临时的垂直线，并标出相平行线间的距离
    displayIncludeAngle(map, mapInfo) {
        let rayLine = this.m_pInterLine;
        if (rayLine.display != 1) {
            return;
        }

        IncludeAngleUtil.display(rayLine.stPoint, rayLine.endPoint,
            rayLine.destStPoint, rayLine.destEndPoint, map, mapInfo);
    }
    setVerticalLine(p1, p2, dstp1, dstp2, dis) {
        let absorbLineSec = this.m_pVerticalLine;
        this.setAbsorbLineSec(absorbLineSec, p1, p2, dstp1, dstp2, dis);
    }

    setParallelLine(p1, p2, dstp1, dstp2, dis) {
        let absorbLineSec = this.m_pParallelLine;
        this.setAbsorbLineSec(absorbLineSec, p1, p2, dstp1, dstp2, dis);
    }

    setInterLine(p1, p2, dstp1, dstp2, dis) {
        let absorbLineSec = this.m_pInterLine;
        this.setAbsorbLineSec(absorbLineSec, p1, p2, dstp1, dstp2, dis);
    }

    setAbsorbLineSec(absorbLineSec, p1, p2, dstp1, dstp2, dis) {
        absorbLineSec.stPoint.x = p1.x;
        absorbLineSec.stPoint.y = p1.y;
        absorbLineSec.endPoint.x = p2.x;
        absorbLineSec.endPoint.y = p2.y;

        absorbLineSec.destStPoint.x = dstp1.x;
        absorbLineSec.destStPoint.y = dstp1.y;
        absorbLineSec.destEndPoint.x = dstp2.x;
        absorbLineSec.destEndPoint.y = dstp2.y;
        absorbLineSec.display = dis;
    }

    hideAuxiliaryGraph() {
        this.m_pVerticalLine.display = 0;
        this.m_pParallelLine.display = 0;
        this.m_pInterLine.display = 0;
        this.setAbsorbPointDis(0);
    }

    setAbsorbPointPos(pt) {
        this.m_pAbsorbPoint.setPt(pt);
    }

    setAbsorbPointDis(dis) {
        this.m_pAbsorbPoint.setDisplay(dis);
    }

    setAbsorbPointKind(kind) {
        this.m_pAbsorbPoint.setKind(kind);
    }
    setSameSizeGroup(graph,dstGraph,kind){
        if (kind == 0){
            this.m_hornSameSizeGroup.setData(graph,dstGraph);
        }
        else if (kind == 1){
            this.m_vertSameSizeGroup.setData(graph,dstGraph);
        }
    }
    resetEditMode(dataManger) {
        
    }

    clearData() {
        
    }
}

export default { AuxDataManager }